package com.bob.common;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.bob.common.bean.*;
import com.bob.common.utils.PomUtil;
import net.sf.json.JSON;
import net.sf.json.xml.XMLSerializer;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;

import java.io.File;
import java.util.*;
import java.util.function.Function;

/**
 * pom 转换 常量
 * @author heh
 */
public class PomReader {
    protected static Log logger = new SystemStreamLog();

    public void initPomDataStore(String rootDir){
        if(!DataStore.getDataStore().getPomEntityMap().isEmpty()){
            return;
        }
        // 从根目录往下寻找pom文件
        List<File> files = getFiles(new File(rootDir));
        // pom文件读取为对象
        files.forEach(file -> {
            PomEntity entity = this.getEntity(file);
            DataStore.getDataStore().getPomAbsolutePathRef().put(entity.getAbsolutePath(),entity.getArtifactId());
            DataStore.getDataStore().getPomEntityMap().put(entity.getArtifactId(),entity);
        });
        // 建立各个子模块与父模块的关系
        DataStore.getDataStore().getPomEntityMap().forEach((artifactId, pomEntity) -> {
            if(pomEntity.getParent()!=null){
                pomEntity.setParent(DataStore.getDataStore().getPomEntityMap().get(pomEntity.getParent().getArtifactId()));
            }
        });
        // 填充各个子模块的dependencies version
        this.setVersion();


        logger.info("=================  DataStore PomEntityMap 初始化成功 ！==========================" );
        logger.debug("=================  DataStore PomEntityMap \n"+ new JSONObject(DataStore.getDataStore().getPomEntityMap()).toJSONString(4));
        logger.info("=================  DataStore PomAbsolutePathRef 初始化成功 ！==========================" );
        logger.debug("=================  DataStore PomAbsolutePathRef \n"+ new JSONObject(DataStore.getDataStore().getPomAbsolutePathRef()).toJSONString(4));
    }

    private JSONObject getJsonObject(File pomFile){
        if(DataStore.getDataStore().getPomJsonObject().containsKey( pomFile.getParentFile().getAbsolutePath())){
            return DataStore.getDataStore().getPomJsonObject().get( pomFile.getParentFile().getAbsolutePath());
        }
        if(pomFile.exists()){
            logger.info(String.format("================= %s Serializer %s==========================" ,pomFile.getAbsolutePath(), "SUCCESS !" ));
            JSON json = new XMLSerializer().readFromFile(pomFile);
            DataStore.getDataStore().getPomJsonObject().put( pomFile.getParentFile().getAbsolutePath(),new JSONObject(json));
            return   DataStore.getDataStore().getPomJsonObject().get( pomFile.getParentFile().getAbsolutePath());
        }
        logger.warn(String.format("=================POM.XML Serializer %s==========================" , "FAIL !!!" ));
        return  new JSONObject();
    }

    public static PomEntity getEntity(String artifactId){
        return DataStore.getDataStore().getPomEntityMap().get(artifactId);
    }

    /**
     * pom.xml 解析为对象
     * @param pomFile
     * @return
     */
    private PomEntity getEntity(File pomFile){
        if(pomFile.exists()){
            JSONObject jsonObject = getJsonObject(pomFile);
            PomEntity pomEntity = jsonObject.toBean(PomEntity.class);
            JSONObject properties = jsonObject.getJSONObject(Constant.Pom.properties);
            JSONObject modules = jsonObject.getJSONObject(Constant.Pom.modules);
            if(modules!=null && !modules.isEmpty()){
                try {
                    JSONArray module = modules.getJSONArray(Constant.Pom.module);
                    pomEntity.setModules(module.toList(String.class));
                }catch (cn.hutool.json.JSONException e){
                    String module = modules.getStr(Constant.Pom.module);
                    ArrayList<String> moduleLists = new ArrayList<>(1);
                    moduleLists.add(module);
                    pomEntity.setModules(moduleLists);
                }
            }

            JSONObject parent = jsonObject.getJSONObject(Constant.Pom.parent);
            if(parent!=null && !parent.isEmpty()) {
                if(!DataStore.getDataStore().getPomEntityMap().isEmpty()){
                    PomEntity entity = new PomEntity();
                        entity.setArtifactId(parent.getStr(Constant.Pom.artifactId));
                    pomEntity.setParent(entity);
                }
            }
            Function<JSONObject,JSONObject> function = (pomJson)->{
                JSONObject dependencyManagement = jsonObject.getJSONObject(Constant.Pom.dependencyManagement);
                if(dependencyManagement!=null && !dependencyManagement.isEmpty()){
                    return dependencyManagement.getJSONObject(Constant.Pom.dependencies);
                }else{
                    return jsonObject.getJSONObject(Constant.Pom.dependencies);
                }
            };
            JSONObject dependencies = function.apply(jsonObject);
            if(dependencies!=null && !dependencies.isEmpty()){
                JSONArray dependency= new JSONArray() ;
                try{
                    dependency = dependencies.getJSONArray(Constant.Pom.dependency);
                }catch (cn.hutool.json.JSONException |ClassCastException  e){
                    JSONObject module = dependencies.getJSONObject(Constant.Pom.dependency);
                    dependency.add(module);
                }
                dependency.forEach(d->{
                    PomBaseEntity pomBaseEntity = new JSONObject(d).toBean(PomBaseEntity.class);
                    if(pomBaseEntity!=null){
                        if(StringUtils.isNotBlank(pomBaseEntity.getArtifactId())  && StringUtils.isNotBlank(pomBaseEntity.getGroupId()) ){
                            if(PomUtil.isProperties(pomBaseEntity.getVersion())){
                                pomBaseEntity.setVersion(properties.getStr(pomBaseEntity.getVersion().replace("${","").replace("}","")));
                            }
                            pomEntity.getDependencies().add(pomBaseEntity);
                        }
                    }
                });
            }
            if(StringUtils.isBlank(pomEntity.getVersion())){
                if(StringUtils.isNotBlank(jsonObject.getStr(Constant.Pom.version))){
                    pomEntity.setVersion(jsonObject.getStr(Constant.Pom.version));
                }else  if(parent!=null && !parent.isEmpty()){
                    pomEntity.setVersion(parent.getStr(Constant.Pom.version,""));
                }
            }

            if(StringUtils.isBlank(pomEntity.getPackaging())){
                if(parent!=null && !parent.isEmpty()) {
                    pomEntity.setVersion(pomEntity.getVersion());
                    pomEntity.setPackaging(pomEntity.getPackaging());
                }
            }
            if(StringUtils.isBlank(pomEntity.getFinalName())){
                pomEntity.setFinalName(PomUtil.finalName(pomEntity.getArtifactId(),pomEntity.getVersion()));
            }
            pomEntity.setAbsolutePath(pomFile.getParentFile().getAbsolutePath());
            return pomEntity;
        }
        return new PomEntity();
    }


    /**
     * 根目录下的pom文件列表
     */
    private List<File> getFiles(File file){
        List<File> fileList = new ArrayList<>();
        if (file.getName().equals(Constant.POM_XML)){
            fileList.add(file);
        }else if (file.isDirectory()){
            for (File filec : Objects.requireNonNull(file.listFiles())) {
                fileList.addAll(getFiles(filec));
            }
        }
        return fileList;
    }

    /**
     * 将pom version 当中的参数引用替换为properties定义的值
     */
    private void setVersion(){
        DataStore.getDataStore().getPomEntityMap().forEach((artifactId, pomEntity) -> {
            List<PomBaseEntity> dependencies = pomEntity.getDependencies();
            dependencies.forEach(dependency->{
                // 如果版本号为空 或者 为变量
                if(StringUtils.isBlank(dependency.getVersion()) || PomUtil.isProperties(dependency.getVersion()) ){
                    PomEntity parent = pomEntity.getParent();
                    boolean has = false;
                    while (!has){
                        if(parent ==null){
                            has =true;
                            continue;
                        }
                        Optional<PomBaseEntity> any = parent.getDependencies().stream().filter(dependencyp ->
                                dependencyp.getArtifactId().equals(dependency.getArtifactId()) &&dependencyp.getGroupId().equals(dependency.getGroupId())
                        ).findAny();
                        if (any.isPresent()){
                            if(StringUtils.isNotBlank(any.get().getVersion())){
                                if(StringUtils.isBlank(any.get().getVersion()) || PomUtil.isProperties(any.get().getVersion())){
                                }else{
                                    dependency.setVersion(any.get().getVersion());
                                    has =true;
                                    continue;
                                }
                            }
                        }
                        parent = parent.getParent();
                    }

                }
            });
        });
    }

}
